﻿
using Xacml.Core;
using System;
using System.Collections;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;

namespace Xacml.Core.Policy
{
  public class PolicyDocumentReadWrite
  {
    private bool _isValidDocument = true;
    private Hashtable _namespaces = new Hashtable();
    public const string XACML_1_0_POLICY_SCHEMA_RESOURCE_NAME = "Xacml.Core.Schemas.cs-xacml-schema-policy-01.xsd";
    public const string XACML_2_0_POLICY_SCHEMA_RESOURCE_NAME = "Xacml.Core.Schemas.access_control-xacml-2.0-policy-schema-cd-01.xsd";
    private PolicySetElementReadWrite _policySet;
    private PolicyElementReadWrite _policy;
    private XacmlVersion _schemaVersion;

    public virtual XacmlVersion Version
    {
      get
      {
        return this._schemaVersion;
      }
      set
      {
        this._schemaVersion = value;
      }
    }

    public virtual bool IsValidDocument
    {
      get
      {
        return this._isValidDocument;
      }
      set
      {
        this._isValidDocument = value;
      }
    }

    public virtual PolicySetElementReadWrite PolicySet
    {
      get
      {
        return this._policySet;
      }
      set
      {
        this._policySet = value;
      }
    }

    public virtual PolicyElementReadWrite Policy
    {
      get
      {
        return this._policy;
      }
      set
      {
        this._policy = value;
      }
    }

    public virtual IDictionary Namespaces
    {
      get
      {
        return (IDictionary) this._namespaces;
      }
      set
      {
        this._namespaces = (Hashtable) value;
      }
    }

    public PolicyDocumentReadWrite(XacmlVersion schemaVersion)
    {
      this._schemaVersion = schemaVersion;
    }

    public PolicyDocumentReadWrite(XmlReader reader, XacmlVersion schemaVersion)
    {
      if (reader == null)
        throw new ArgumentNullException("reader");
      this._schemaVersion = schemaVersion;
      XmlValidatingReader validatingReader = new XmlValidatingReader(reader);
      try
      {
        switch (schemaVersion)
        {
          case XacmlVersion.Version10:
          case XacmlVersion.Version11:
            XmlTextReader xmlTextReader1 = new XmlTextReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("Xacml.Core.Schemas.cs-xacml-schema-policy-01.xsd"));
            validatingReader.Schemas.Add("urn:oasis:names:tc:xacml:1.0:policy", (XmlReader) xmlTextReader1);
            break;
          case XacmlVersion.Version20:
            XmlTextReader xmlTextReader2 = new XmlTextReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("Xacml.Core.Schemas.access_control-xacml-2.0-policy-schema-cd-01.xsd"));
            validatingReader.Schemas.Add("urn:oasis:names:tc:xacml:2.0:policy", (XmlReader) xmlTextReader2);
            break;
          default:
            throw new ArgumentException(Resource.ResourceManager[Resource.MessageKey.exc_invalid_version_parameter_value], "version");
        }
        validatingReader.ValidationEventHandler += new ValidationEventHandler(this.vreader_ValidationEventHandler);
        while (validatingReader.Read())
        {
          if (validatingReader.HasAttributes)
          {
            while (validatingReader.MoveToNextAttribute())
            {
              if (validatingReader.LocalName == "xmlns")
                this._namespaces.Add((object) validatingReader.Prefix, (object) validatingReader.Value);
              else if (validatingReader.Prefix == "xmlns")
                this._namespaces.Add((object) validatingReader.LocalName, (object) validatingReader.Value);
            }
            validatingReader.MoveToElement();
          }
          switch (validatingReader.LocalName)
          {
            case "PolicySet":
              this._policySet = new PolicySetElementReadWrite((XmlReader) validatingReader, schemaVersion);
              return;
            case "Policy":
              this._policy = new PolicyElementReadWrite((XmlReader) validatingReader, schemaVersion);
              return;
            default:
              continue;
          }
        }
      }
      finally
      {
        if (validatingReader != null)
          validatingReader.Close();
      }
    }

    private void vreader_ValidationEventHandler(object sender, ValidationEventArgs e)
    {
      Console.WriteLine(e.Message);
      Console.WriteLine();
      this._isValidDocument = false;
    }

    public void WriteDocument(XmlWriter writer)
    {
      writer.WriteStartDocument();
      if (this._policySet != null)
        this._policySet.WriteDocument(writer, this._namespaces);
      else if (this._policy != null)
        this._policy.WriteDocument(writer, this._namespaces);
      writer.WriteEndDocument();
    }
  }
}
